#include <mpi.h>
#include <stdio.h>

int main(int argc, char **argv) {
  int commnum = 0;      /* which of the 3 comms I belong to */
  MPI_Comm mycomm;      /* Communicator I belong to */
  MPI_Comm intercomm;   /* inter-communicator */
  int cw_rank, cw_size; /* size, rank in MPI_COMM_WORLD */
  int rank;             /* rank in local communicator */

  MPI_Init(&argc, &argv);
  MPI_Comm_rank(MPI_COMM_WORLD, &cw_rank);
  MPI_Comm_size(MPI_COMM_WORLD, &cw_size);

  if (cw_rank < 3)
    commnum = 0;
  else
    commnum = 1;
  // mpi_bool
  // mpi_shor
  /* split MPI_COMM_WORLD */
  MPI_Comm_split(MPI_COMM_WORLD, commnum, cw_rank, &mycomm);
  printf("Rank %d in COMM %d...\n", cw_rank, commnum);

  const int icomm_tag = 1;
  if (commnum == 0) {
    int local_leader = 0;
    int remote_leader = 3; /* rank in peer_comm */
    MPI_Intercomm_create(mycomm, local_leader, MPI_COMM_WORLD, remote_leader,
                         icomm_tag, &intercomm);
  } else {
    int local_leader = 0;
    int remote_leader = 0;
    MPI_Intercomm_create(mycomm, local_leader, MPI_COMM_WORLD, remote_leader,
                         icomm_tag, &intercomm);
  }

  /* broadcast data from local group to remote group*/
  if (commnum == 1) {
    int bcast_data = 0;
    int lr_size;
    int local_leader = 0;

    MPI_Comm_rank(mycomm, &rank);
    if (rank == 0)
      bcast_data = 6666;

    /* MPI_Bcast by intercommunicator*/
    int root_proc;
    if (rank == 0)
      root_proc = MPI_ROOT;
    else
      root_proc = MPI_PROC_NULL;
    MPI_Bcast(&bcast_data, 1, MPI_INT, root_proc, intercomm);
    // 同一个进程组没有被 Bcast
    printf("Rank %d receive bcast_data: %d\n", rank, bcast_data);
  }

  if (commnum == 0) {
    int bcast_data = 8888;
    int remote_leader = 0; /*rank in remote_comm*/

    MPI_Comm_rank(mycomm, &rank);
    MPI_Bcast(&bcast_data, 1, MPI_INT, remote_leader, intercomm);
    printf("Rank %d receive bcasted bcast_data: %d\n", rank, bcast_data);
  }

  MPI_Comm_free(&intercomm);
  MPI_Finalize();
  return 0;
}